#include "rtconfig.h"
#include "rtthread.h"
#include <rtdevice.h>
#include "finsh.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define RX_BUFFER_SIZE 128
static struct rt_completion completion;
static uint8_t rx_buffer[RX_BUFFER_SIZE];
static uint16_t cur_pos;
static rt_device_t dev;

#if 1

static rt_err_t usart1_rx_ind(rt_device_t dev, rt_size_t size)
{
    rt_completion_done(&completion);
    return 0;
}

static void usart1Test(int argc, char **args)
{
    rt_size_t res;

    rt_completion_init(&completion);
    dev = rt_device_find("uart1");

    rt_err_t ret = rt_device_open(dev, RT_DEVICE_FLAG_RX_NON_BLOCKING|RT_DEVICE_FLAG_TX_BLOCKING);
    
    if(ret != RT_EOK) {
        printf("Open device failed!\r\n");
        return;
    }

    cur_pos = 0;
    memset(rx_buffer, 0, RX_BUFFER_SIZE);
    rt_device_set_rx_indicate(dev, usart1_rx_ind);

    while(1)
    {
        res = rt_device_read(dev, 0, rx_buffer + cur_pos, RX_BUFFER_SIZE - cur_pos);
        if(res > 0) {
            cur_pos += res;
            if (rx_buffer[cur_pos - 1] == '\n') {
                rt_device_write(dev, 0, rx_buffer, cur_pos);
                cur_pos = 0;
            } else if (cur_pos >= RX_BUFFER_SIZE) {
                cur_pos = 0;
                printf("Too large message!!!\r\n");
            }
        } else if(res == 0) {
            ret = rt_completion_wait(&completion, RT_WAITING_FOREVER);
            if (ret != RT_EOK) {
                printf("rt_completion_wait return error\r\n");
                break;
            }
        } else {
            printf("rt_device_read return error\r\n");
            break;
        }        
    }

}

#else

static rt_err_t usart1_rx_ind(rt_device_t dev, rt_size_t size)
{
    if(cur_pos + size > RX_BUFFER_SIZE) {
        size = RX_BUFFER_SIZE - cur_pos;
    }
    rt_size_t ret = rt_device_read(dev, 0, rx_buffer + cur_pos, size);
    if(ret > 0) {
        cur_pos += ret;
    }

    if(rx_buffer[cur_pos-2] == '\r' && rx_buffer[cur_pos-1] == '\n') {
        rt_completion_done(&completion);
    } else if(cur_pos >= RX_BUFFER_SIZE) {
        cur_pos = 0;
        printf("Too large message!!!\r\n");
    }

    return 0;
}

static void usart1Test(int argc, char **args)
{
    rt_completion_init(&completion);

    dev = rt_device_find("uart1");
    rt_err_t ret = rt_device_open(dev, RT_DEVICE_FLAG_INT_RX|RT_DEVICE_FLAG_RDWR);
    
    if(ret != RT_EOK) {
        printf("Open device failed!\r\n");
        return;
    }

    cur_pos = 0;
    memset(rx_buffer, 0, RX_BUFFER_SIZE);
    rt_device_set_rx_indicate(dev, usart1_rx_ind);

    //rt_device_write(dev, 0, "this is a test!\r\n", 17);
    while(1) {
        ret = rt_completion_wait(&completion, RT_WAITING_FOREVER);
        if (ret != RT_EOK) {
            break;
        }

        rt_device_write(dev, 0, rx_buffer, cur_pos);
        cur_pos = 0;
    }
}

#endif

MSH_CMD_EXPORT_ALIAS(usart1Test, usart1test, This is a usart1 test!);
